package com.gomoku.botrunning.utils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;

public class Bot4 implements java.util.function.Supplier<JSONObject> {
    private static final int BOARD_SIZE = 16;
    private static final int[][] DIRS = {{0, 1}, {1, 0}, {1, 1}, {1, -1}}; // 四个主要方向
    private static final Random random = new Random();

    // 定义不同棋型的权重分数
    private static final Map<String, Integer> MOVE_VALUES = new HashMap() {{
        put("FIVE", 100000);   // 五连必胜
        put("LIVE_FOUR", 50000); // 活四
        put("DEAD_FOUR", 1000);  // 眠四
        put("LIVE_THREE", 3000); // 活三
        put("DEAD_THREE", 500);  // 眠三
        put("LIVE_TWO", 200);    // 活二
        put("BLOCK_FIVE", 80000);// 阻挡对方五连
        put("BLOCK_FOUR", 40000);// 阻挡对方活四
        put("BLOCK_THREE", 2000);// 阻挡对方活三
    }};

    @Override
    public JSONObject get() {
        File file = new File("input.txt");
        try (Scanner sc = new Scanner(file)) {
            return nextMove(sc.next());
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    public JSONObject nextMove(String input) {
        int[][] map = JSON.parseObject(input, int[][].class);
        JSONObject bestMove = null;
        int bestScore = Integer.MIN_VALUE;

        // 1. 检查是否可以立即获胜（五连）
        List<JSONObject> winningMoves = findWinningMoves(map, 2);
        if (!winningMoves.isEmpty()) {
            return winningMoves.get(random.nextInt(winningMoves.size()));
        }

        // 2. 检查是否需要防守对方即将获胜
        List<JSONObject> blockingMoves = findBlockingMoves(map, 1);
        if (!blockingMoves.isEmpty()) {
            return blockingMoves.get(random.nextInt(blockingMoves.size()));
        }

        // 3. 寻找最佳进攻位置
        for (int r = 1; r < BOARD_SIZE; r++) {
            for (int c = 1; c < BOARD_SIZE; c++) {
                if (map[r][c] == 0) { // 空位才考虑
                    int score = evaluatePosition(map, r, c, 2); // 评估白棋在此落子的得分
                    if (score > bestScore) {
                        bestScore = score;
                        bestMove = new JSONObject();
                        bestMove.put("r", r);
                        bestMove.put("c", c);
                    }
                }
            }
        }

        // 4. 如果没有任何理想位置，随机落子
        if (bestMove == null) {
            List<JSONObject> emptySpots = new ArrayList<>();
            for (int r = 1; r < BOARD_SIZE; r++) {
                for (int c = 1; c < BOARD_SIZE; c++) {
                    if (map[r][c] == 0) {
                        JSONObject res = new JSONObject();
                        res.put("r",r);
                        res.put("c",c);
                        emptySpots.add(res);
                    }
                }
            }
            if (!emptySpots.isEmpty()) {
                bestMove = emptySpots.get(random.nextInt(emptySpots.size()));
            }
        }

        return bestMove != null ? bestMove : new JSONObject(); // 确保永不返回null
    }

    // 寻找所有能立即获胜的着法
    private List<JSONObject> findWinningMoves(int[][] map, int player) {
        List<JSONObject> moves = new ArrayList<>();
        for (int r = 1; r < BOARD_SIZE; r++) {
            for (int c = 1; c < BOARD_SIZE; c++) {
                if (map[r][c] == 0) {
                    int[][] tempMap = deepCopy(map);
                    tempMap[r][c] = player;
                    if (checkWin(tempMap, player)) {
                        JSONObject res = new JSONObject();
                        res.put("r",r);
                        res.put("c",c);
                        moves.add(res);
                    }
                }
            }
        }
        return moves;
    }

    // 寻找必须阻挡的对手着法
    private List<JSONObject> findBlockingMoves(int[][] map, int opponent) {
        List<JSONObject> moves = new ArrayList<>();
        for (int r = 1; r < BOARD_SIZE; r++) {
            for (int c = 1; c < BOARD_SIZE; c++) {
                if (map[r][c] == 0) {
                    int[][] tempMap = deepCopy(map);
                    tempMap[r][c] = 2; // 我们在这里落子
                    if (checkWin(tempMap, opponent)) { // 如果对手在这里会赢
                        JSONObject res = new JSONObject();
                        res.put("r",r);
                        res.put("c",c);
                        moves.add(res);
                    }
                }
            }
        }
        return moves;
    }

    // 评估指定位置的价值分数
    private int evaluatePosition(int[][] map, int r, int c, int player) {
        int score = 0;
        int[][] tempMap = deepCopy(map);
        tempMap[r][c] = player; // 模拟落子

        // 计算该位置形成的棋型价值
        for (int[] dir : DIRS) {
            String pattern = analyzeLine(tempMap, r, c, dir[0], dir[1], player);
            score += MOVE_VALUES.getOrDefault(pattern, 0);
        }
        return score;
    }

    // 分析某一行的棋型模式
    private String analyzeLine(int[][] map, int r, int c, int dr, int dc, int player) {
        int count = 1; // 当前棋子本身
        int emptyBefore = 0, emptyAfter = 0;

        // 向前搜索
        for (int step = 1; ; step++) {
            int nr = r + dr * step;
            int nc = c + dc * step;
            if (nr <= 0 || nr >= BOARD_SIZE || nc <= 0 || nc >= BOARD_SIZE) break;
            if (map[nr][nc] == player) count++;
            else if (map[nr][nc] == 0) emptyAfter++;
            else break; // 遇到对方棋子
        }

        // 向后搜索
        for (int step = 1; ; step++) {
            int nr = r - dr * step;
            int nc = c - dc * step;
            if (nr <= 0 || nr >= BOARD_SIZE || nc <= 0 || nc >= BOARD_SIZE) break;
            if (map[nr][nc] == player) count++;
            else if (map[nr][nc] == 0) emptyBefore++;
            else break; // 遇到对方棋子
        }

        // 根据统计结果判断棋型
        switch (count) {
            case 5: return "FIVE";
            case 4:
                if (emptyBefore + emptyAfter >= 2) return "LIVE_FOUR";
                else return "DEAD_FOUR";
            case 3:
                if (emptyBefore + emptyAfter >= 2) return "LIVE_THREE";
                else return "DEAD_THREE";
            case 2:
                if (emptyBefore + emptyAfter >= 2) return "LIVE_TWO";
                break;
        }
        return "NONE";
    }

    // 检查是否获胜
    private boolean checkWin(int[][] map, int player) {
        for (int r = 1; r < BOARD_SIZE; r++) {
            for (int c = 1; c < BOARD_SIZE; c++) {
                if (map[r][c] != player) continue;
                for (int[] dir : DIRS) {
                    int count = 1;
                    for (int step = 1; step < 5; step++) {
                        int nr = r + dir[0] * step;
                        int nc = c + dir[1] * step;
                        if (nr <= 0 || nr >= BOARD_SIZE || nc <= 0 || nc >= BOARD_SIZE || map[nr][nc] != player) break;
                        count++;
                    }
                    if (count >= 5) return true;
                }
            }
        }
        return false;
    }

    // 深拷贝二维数组
    private int[][] deepCopy(int[][] original) {
        int[][] copy = new int[BOARD_SIZE][BOARD_SIZE];
        for (int i = 1; i < BOARD_SIZE; i++) {
            System.arraycopy(original[i], 0, copy[i], 0, BOARD_SIZE);
        }
        return copy;
    }
}